package moore.generator.template

import java.util.ArrayList
import moore.valueState
import moore.conditionState
import java.util.List

class MsfFTemplate {
	def public static String getMsfF(String asmName,ArrayList<String> fInputs,
		int stateDim, List<valueState> states
	){
		var String inLineInputs="";
		for(var i=0; i<fInputs.size;i++){
			inLineInputs+=","+fInputs.get(i);
		}
		'''
		library IEEE;
		use IEEE.STD_LOGIC_1164.ALL;
		
		entity «asmName»_F is
		PORT(
			«FOR in:fInputs»
			«in»: in std_logic;
			«ENDFOR»
			prev_state: in std_logic_vector («stateDim-1» downto 0);
			next_state: out std_logic_vector («stateDim-1» downto 0)
		);
		end «asmName»_F;
		
		architecture Behavioral of «asmName»_F is
			signal next_state_int:std_logic_vector («stateDim-1» downto 0):=(others=>'0');
		begin
			next_state<=next_state_int;
			next_state_process: process(prev_state «inLineInputs»)
			begin
				case prev_state is
					«FOR state:states»
					«generateStateWhen(state)»
					«ENDFOR»
					when others =>
						next_state_int<="«generateOthers(stateDim)»";
				end case;
			end process;
		end Behavioral;			
		'''
	}
	
	def private static String generateStateWhen(valueState state){
		'''
			when "«state.name»"=>
				«IF state.outputState instanceof conditionState»
				«generateCondState(state.outputState as conditionState)»
				«ENDIF»
				«IF state.outputState instanceof valueState»
				«generateStateInt(state)»
				«ENDIF»
		'''
	}
	
	def private static String generateStateInt(valueState state){
		'''
			next_state_int<="«state.outputState.name»";
		'''
	}
	
	def private static String generateCondState(conditionState conditional){
		'''
			if(«conditional.inputSignal.name»='«conditional.inputSignal.value.value»')then
				«IF conditional.outputState instanceof valueState»
				next_state_int<="«conditional.outputState.name»";
				else
				«IF conditional.falseOutputState instanceof valueState»
				next_state_int<="«conditional.falseOutputState.name»";
				«ELSE»
				«generateCondState(conditional.falseOutputState as conditionState)»
				«ENDIF»
				«ELSE»	
				«generateCondState(conditional.outputState as conditionState)»
			«ENDIF»		
			end if;
		'''
	}
	
	def private static String generateOthers(int stateDim){
		var String others="";
		for(var i=0; i<stateDim; i++){
			others+="0";
		}
		return others;
	}
}